// $codepro.audit.disable numericLiterals, methodChainLength
/**
 * @author Team Awesome Express
 * @version 1.0
 */

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.GroupLayout;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.JTextArea;
import javax.swing.JButton;


import java.io.IOException;
import java.util.Calendar;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.awt.Color;
import javax.swing.JTextField;


/**
 * Appointment Page for Patient
 * displays preferred date, time, and doctor and reason for visit
 * @author Marcus
 * @version $Revision: 1.0 $
 */
public class AppointmentFrame{

	
	/**
	 * Field MYLOGGER.
	 */
	private static final Logger MYLOGGER = Logger.getLogger("./AppointmentFrame");

	/**
	 * Field myDataManager.
	 */
	private final DataManager myDataManager;

	/**
	 * Field userLength.
	 * First and last name for user's name.
	 */
	private static final int USERLENGTH = 2; // $codepro.audit.disable numericLiterals
	
	/**
	 * Field dateLength
	 * Length for the amount of dates the appointment page can hold
	 */
	private static final int DATELENGTH = 30;

 static {
         
         final ConsoleHandler ch = new ConsoleHandler();
         ch.setLevel(Level.ALL);
         ch.setFormatter(new SimpleFormatter());
         MYLOGGER.addHandler(ch);
         MYLOGGER.setLevel(Level.ALL);
         MYLOGGER.setUseParentHandlers(true);
         
         try {
             final FileHandler fh = new FileHandler("Appointments.html");
             fh.setFormatter(new HTMLFormatter());
             MYLOGGER.addHandler(fh);
         } catch (SecurityException e) {
             MYLOGGER.log(Level.SEVERE, "Security Exception creating a file handler", e);
             e.printStackTrace();
         } catch (IOException e) {
             MYLOGGER.log(Level.SEVERE, "IO Exception creating a file handler", e);
             e.printStackTrace();
         } 
         
     }
	
	/**
	 * Field username.
	 */
	private String[] username = new String[USERLENGTH];

	/**
	 * Field dates.
	 */
	private final String[] dates = new String[DATELENGTH];

	/**
	 * Field time.
	 */
	private final String[] time = 
	{"(default)",
	 "9:00 AM", 
	 "10:00 AM", 
	 "11:00 AM", 
	 "12:00 PM", 
	 "1:00 PM", 
	 "2:00 PM", 
	 "3:00 PM", 
	 "4:00 PM", 
	 "5:00 PM"
	 };

	/**
	 * Field doctors.
	 */
	private final String[] doctors = 
	{"(default)", "David Johnson", "Susan Smith", "Marcus Fonder"};

	/**
	 * Field doctorStr.
	 */
	private String doctorStr = "";

	/**
	 * Field timeStr.
	 */
	private String timeStr = "";

	/**
	 * Field dateStr.
	 */
	private String dateStr = "";
	
	/**
	 * Field lblDesiredDate.
	 */
	private JLabel lblDesiredDate;

	/**
	 * Field lblTime.
	 */
	private JLabel lblTime;

	/**
	 * Field lblDesiredDoctor.
	 */
	private JLabel lblDesiredDoctor;

	/**
	 * Field lblReasonForAppointment.
	 */
	private JLabel lblReasonForAppointment;
	
	/**
	 * Field dateSP.
	 */
	private JScrollPane dateSP;

	/**
	 * Field timeSP.
	 */
	private JScrollPane timeSP;

	/**
	 * Field doctorSP.
	 */
	private JScrollPane doctorSP;

	/**
	 * Field descrptSP.
	 */
	private JScrollPane descrptSP;
	
	/**
	 * Field doctorList.
	 */
	private JList doctorList;

	/**
	 * Field timeList.
	 */
	private JList timeList;

	/**
	 * Field dateList.
	 */
	private JList dateList;
	
	/**
	 * Field descrptTA.
	 */
	private JTextArea descrptTA;
	
	/**
	 * Field frmAppointmentPage.
	 */
	private JFrame frmAppointmentPage;

	/**
	 * Field warning.
	 */
	private WarningMsg warning;
	
	/**
	 * Field userType.
	 */
	private final int userType;

	/**
	 * Field txtUserid.
	 */
	private JTextField txtUserid;

	/**
	 * Field txtFirstName.
	 */
	private JTextField txtFirstName;

	/**
	 * Field txtLastName.
	 */
	private JTextField txtLastName;

	/**
	 * Field lblIDErr.
	 */
	private JLabel lblIDErr;

	/**
	 * Field lblFirstNameErr.
	 */
	private JLabel lblFirstNameErr;

	/**
	 * Field lblLastNameErr.
	 */
	private JLabel lblLastNameErr;
	
	/**
	 * Field foundErr.
	 */
	private boolean foundErr;

	/**
	 * Field apptPage.
	 */
	private ViewAppointment.ApptTableModel apptPage;

	/**
	 * Create the application.
	 * @param dataManager DataManager
	 * @param usertype int
	 */
	public AppointmentFrame(DataManager dataManager, int usertype) {
		foundErr = true;
		userType = usertype;
		recieveCurrDate();
		myDataManager = dataManager;
		initialize();
	}

	/**
	 * constructor
	 * 
	 * @param dataManager
	 * @param usertype
	 * @param userid
	 * @param firstName
	 * @param lastName
	 * @param date
	 * @param time
	 * @param doctor
	 * @param reason
	 */
	public AppointmentFrame(DataManager dataManager, // $codepro.audit.disable largeNumberOfParameters
			int usertype,
			String userid,
			String firstName,
			String lastName,
			String date,
			String time,
			String doctor,
			String reason){
		foundErr = true;
		userType = usertype;
		myDataManager = dataManager;
		recieveCurrDate();
		
		this.txtUserid.setText(userid);
		this.txtFirstName.setText(firstName);
		this.txtLastName.setText(lastName);
		this.dateStr = date;
		this.timeStr = time;
		this.doctorStr = doctor;
		this.descrptTA.setText(reason);
		
		final String[] data = {userid, firstName, lastName, date, time, doctor, reason};
		
		myDataManager.setData(GlobalVars.APPOINTMENT_SHEET, null, data, -1);
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmAppointmentPage = new JFrame();
		frmAppointmentPage.getContentPane().setBackground(GlobalVars.BACKGROUND); // $codepro.audit.disable numericLiterals
		frmAppointmentPage.setTitle("Appointment Page");
		frmAppointmentPage.setBounds(100, 100, 390, 431); // $codepro.audit.disable numericLiterals
		frmAppointmentPage.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		
		lblDesiredDate = new JLabel("Desired Date");
		lblTime = new JLabel("Time");
		lblDesiredDoctor = new JLabel("Desired Doctor");
		lblReasonForAppointment = new JLabel("Reason for appointment");
		
		dateSP = new JScrollPane();
		timeSP = new JScrollPane();
		doctorSP = new JScrollPane();
		descrptSP = new JScrollPane();
		
		doctorList = new JList(doctors);
		doctorSP.setColumnHeaderView(doctorList);
		doctorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		doctorList.setSelectedIndex(0);	//default selection setup for date
		doctorList.addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e){
				final Object doctorObj = doctorList.getSelectedValue();
					doctorStr = (String) doctorObj;
			}
		});
		
		timeList = new JList(time);
		timeSP.setViewportView(timeList);
		timeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		timeList.setSelectedIndex(0);	//default selection setup for date
		timeList.addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e){
				final Object timeObj = timeList.getSelectedValue();
					timeStr = (String) timeObj;
			}
		});
		
		dateList = new JList(dates);
		dateSP.setViewportView(dateList);
		dateList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		dateList.setSelectedIndex(0);	//default selection setup for date
		dateList.addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e){
				final Object dateObj = dateList.getSelectedValue();
					dateStr = (String) dateObj;
			}
		});
		
		descrptTA = new JTextArea();
		descrptTA.setText("N/A");
		descrptSP.setViewportView(descrptTA);
		
		final JLabel lblUserid = new JLabel("UserID");
		
		txtUserid = new JTextField();
		txtUserid.setColumns(10);
		
		final JLabel lblFirstName = new JLabel("First Name");
		
		txtFirstName = new JTextField();
		txtFirstName.setColumns(10);
		
		final JLabel lblLastName = new JLabel("Last Name");
		
		txtLastName = new JTextField();
		txtLastName.setColumns(10);
		
		lblIDErr = new JLabel("Not existing ID");
		lblIDErr.setForeground(Color.RED);
		
		lblFirstNameErr = new JLabel("Verify the information");
		lblFirstNameErr.setForeground(Color.RED);
		
		lblLastNameErr = new JLabel("Verify the information");
		lblLastNameErr.setForeground(Color.RED);
		
		//if it's patient, this will set patient's information
		if(userType == GlobalVars.PATIENT_USERTYPE){
			txtUserid.setText(myDataManager.username);
			txtUserid.setEnabled(false);
			
			//set user's first and last name
			setUsername(myDataManager.userInfo(myDataManager.username, userType));
			
			txtFirstName.setText(username[0]);
			txtFirstName.setEnabled(false);
			
			txtLastName.setText(username[1]);
			txtLastName.setEnabled(false);
		}
		else{
			apptPage = new ViewAppointment.ApptTableModel(myDataManager);
		}

		final JButton btnSubmit = new JButton("Submit");
		btnSubmit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				lblIDErr.setVisible(false);
				lblFirstNameErr.setVisible(false);
				lblLastNameErr.setVisible(false);
				
				//check for missing information
				if(dateList.getSelectedIndex() == 0 ||
						timeList.getSelectedIndex() == 0 ||
						doctorList.getSelectedIndex() == 0 ||
						txtUserid.getText().equals("") ||
						txtFirstName.getText().equals("") ||
						txtLastName.getText().equals("")){
					warning = new WarningMsg();
				}
				else{
					//User id, first name, last name Data integrity check
					int rowNum = -1;
					boolean isIDExist = false;
					foundErr = false;
					final String[] idList = myDataManager.getDataAtCol(GlobalVars.PATIENT_SHEET, "User Name", "User Name");
					for(int i=0; i < idList.length; i++){
						if(idList[i].equals(txtUserid.getText())){
							isIDExist = true;
							rowNum = i;
						}
					}
					
					if(!isIDExist){
						lblIDErr.setVisible(true);
						foundErr = true;
					}
					else{
						final String[] firstNameList = myDataManager.getDataAtCol(GlobalVars.PATIENT_SHEET, "First Name", "First Name");
						final String[] lastNameList = myDataManager.getDataAtCol(GlobalVars.PATIENT_SHEET, "Last Name", "Last Name");
						if(!firstNameList[rowNum].equals(txtFirstName.getText())){
							lblFirstNameErr.setVisible(true);
							foundErr = true;
						}
						if(!lastNameList[rowNum].equals(txtLastName.getText())){
							lblLastNameErr.setVisible(true);
							foundErr = true;
						}
					}
					
					// if every information is correct
					if(!foundErr){
						/*
						 * Can not put reason for appointment 
						 * due to the fact that it causes
						 * a log forging error when being audited. 
						 * We can remove this rule from the file however. 
						 * Here is the last part of the string
						 * that was deleted:
						 *  + "\n"	+
						 * "The reason for the visit is: \n " + descrptTA.getText());
						 * THEN FIX IT MARCUS
						 */
						MYLOGGER.log(Level.FINE, "Doctor " + doctorStr +
									" has been schedule an appointment on " + dateStr + 
									" at " + timeStr);
										
						final String[] data = {txtUserid.getText(),
										 txtFirstName.getText(), 
										 txtLastName.getText(), 
										 dateStr,
										 timeStr, 
										 doctorStr, 
										 descrptTA.getText()}; //put appointment data into data array 

						if(userType != GlobalVars.PATIENT_USERTYPE){
							//if medical staff access this frame, add new appointment to the table in ViewAppointment
							apptPage.addData(data);
							//apptPage.removeRow(1);
							
						}
						else{
							myDataManager.setData(GlobalVars.APPOINTMENT_SHEET, null, data, -1);	//write appointment data in the appointment sheet 
						}
					    					
						frmAppointmentPage.dispose();
					}
				}
			}
		});
				
		final JButton btnCancel = new JButton("Cancel");
		btnCancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				frmAppointmentPage.dispose();
			}
		});

		final GroupLayout groupLayout = new GroupLayout(frmAppointmentPage.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addGap(107)
							.addComponent(btnSubmit)
							.addGap(18)
							.addComponent(btnCancel))
						.addGroup(groupLayout.createSequentialGroup()
							.addContainerGap()
							.addComponent(lblReasonForAppointment))
						.addGroup(groupLayout.createSequentialGroup()
							.addContainerGap()
							.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
								.addGroup(groupLayout.createSequentialGroup()
									.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
										.addComponent(dateSP, GroupLayout.PREFERRED_SIZE, 84, GroupLayout.PREFERRED_SIZE)
										.addComponent(lblDesiredDate)
										.addComponent(lblIDErr))
									.addGap(31)
									.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING, false)
										.addGroup(groupLayout.createSequentialGroup()
											.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING, false)
												.addGroup(groupLayout.createSequentialGroup()
													.addComponent(lblFirstNameErr)
													.addGap(18)
													.addComponent(lblLastNameErr))
												.addGroup(groupLayout.createSequentialGroup()
													.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
														.addComponent(timeSP, GroupLayout.PREFERRED_SIZE, 74, GroupLayout.PREFERRED_SIZE)
														.addComponent(lblTime))
													.addPreferredGap(ComponentPlacement.RELATED, 56, Short.MAX_VALUE)
													.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
														.addComponent(lblDesiredDoctor)
														.addComponent(doctorSP, GroupLayout.PREFERRED_SIZE, 96, GroupLayout.PREFERRED_SIZE))))
											.addGap(363))
										.addGroup(groupLayout.createSequentialGroup()
											.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
												.addGroup(groupLayout.createSequentialGroup()
													.addComponent(lblFirstName)
													.addGap(70))
												.addGroup(groupLayout.createSequentialGroup()
													.addComponent(txtFirstName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
													.addGap(35)))
											.addPreferredGap(ComponentPlacement.RELATED, 10, Short.MAX_VALUE)
											.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
												.addComponent(txtLastName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
												.addComponent(lblLastName))
											.addGap(373))))
								.addComponent(descrptSP, Alignment.LEADING, GroupLayout.PREFERRED_SIZE, 344, GroupLayout.PREFERRED_SIZE)))
						.addGroup(groupLayout.createSequentialGroup()
							.addContainerGap()
							.addComponent(txtUserid, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
						.addGroup(groupLayout.createSequentialGroup()
							.addContainerGap()
							.addComponent(lblUserid)))
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblUserid)
						.addComponent(lblFirstName)
						.addComponent(lblLastName))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(txtUserid, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(txtFirstName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(txtLastName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblIDErr)
						.addComponent(lblFirstNameErr)
						.addComponent(lblLastNameErr))
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblDesiredDate)
						.addComponent(lblTime)
						.addComponent(lblDesiredDoctor))
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(dateSP, GroupLayout.PREFERRED_SIZE, 96, GroupLayout.PREFERRED_SIZE)
						.addComponent(timeSP, GroupLayout.PREFERRED_SIZE, 95, GroupLayout.PREFERRED_SIZE)
						.addComponent(doctorSP, GroupLayout.PREFERRED_SIZE, 96, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(lblReasonForAppointment)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(descrptSP, GroupLayout.PREFERRED_SIZE, 104, GroupLayout.PREFERRED_SIZE)
					.addGap(18)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(btnCancel)
						.addComponent(btnSubmit))
					.addGap(19))
		);
		lblIDErr.setVisible(false);
		lblFirstNameErr.setVisible(false);
		lblLastNameErr.setVisible(false);
		
		frmAppointmentPage.getContentPane().setLayout(groupLayout);
		frmAppointmentPage.setVisible(true);
	}
	
	/**
	 * Method setUsername.
	 * @param name String
	 */
	public void setUsername(String name){
		username = name.split(" ");
	}

	/**
	 * get 30 days of current date start from today
	 */
	public void recieveCurrDate(){
		//sunday: 1, monday: 2 (day of week)
		final Calendar calendar = Calendar.getInstance();
		int day = calendar.get(Calendar.DATE);
		int month = calendar.get(Calendar.MONTH) + 1;
		final int year = calendar.get(Calendar.YEAR);
		
		int index = 1;
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
		dates[0] = "(default)";
		while(index < 30){
			//check day is the last day of this month 
			if(calendar.getActualMaximum(Calendar.DATE) >= day){
				//check whether it's weekend or not (Saturday: 7, Sunday: 1)
				if(dayOfWeek != 7 && dayOfWeek != 1){
					//check whether it's after 5PM
					if(Calendar.HOUR_OF_DAY < 18){ // $codepro.audit.disable constantCondition, constantConditionalExpression, comparisonOfConstants
						dates[index] = Integer.toString(month) + "/" + Integer.toString(day) + "/" + Integer.toString(year);
						index++;
					}
				}
				if(dayOfWeek == 7){
					dayOfWeek = 0;
				}
				day++;	//get next day
				dayOfWeek++;
			}
			else{
				day = 1;
				if(month == 12){
					month = 1;
				}
				else{
					month = month + 1;
				}
			}
			calendar.set(year, month, day, 9, 0);
		}
	}
	
	/**
	 * Warning Message Pane for missing information
	 * @author Marcus
	 */
	public static class WarningMsg{
		/**
		 * Constructor for WarningMsg.
		 */
		public WarningMsg(){
			final String msg="Missing Information.";
			JOptionPane.showMessageDialog(null, msg, "Warning", JOptionPane.WARNING_MESSAGE); //$codepro.audit.disable lineLength
		}
	}
	

}
